<?php

namespace App\Model;

use Hyperf\Collection\Collection;
use Hyperf\Context\ApplicationContext;
use Hyperf\Database\Model\Relations\BelongsTo;
use Hyperf\Database\Model\Relations\BelongsToMany;
use Hyperf\Database\Model\Relations\HasMany;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Arr;
use Hyperf\Redis\Redis;
use Carbon\Carbon;
use PHPUnit\Util\Test;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use RedisException;


class Device extends Model
{
    const SIGNAL_TIME_OUT = 'signal_time_out';

    public bool $timestamps = true;
    protected ?string $table = 'devices';

    private const GEO_KEY = 'devices:geo';

    const ONLINE = 1;// 设备在线
    const NOT_ONLINE = 0;// 设备不在线

    protected array $guarded = ['id'];

    protected array $casts = [
        'last_online_at' => 'datetime',
        'active_at' => 'datetime',
        'expires_at' => 'datetime',
        'created_at'=>'datetime',
        'params_read_at' => 'datetime',
    ];

    const CHANNEL_MAX = 10;
//    const JOIN_DEPOSIT_FEE = 200;

    const RENEW_FEE = 25.00;


    public function portErr(){
        return $this->hasMany(DevicePortErrLog::class,'device_id','id');
    }
    public function device_profit(){
        return $this->hasMany(DistributorDevice::class,'device_id','id');
    }

    public function distributor(){
        return $this->belongsTo(Distributors::class,'distributor_id','id');
    }
    public function station() :BelongsTo{
        return $this->belongsTo(Station::class,'station_id','id');
    }
    public function orders()
    {
        return $this->hasMany(Order::class,'device_id','id');
    }
    public function port():HasMany{
        return $this->hasMany(DevicePort::class,'device_id','id');
    }

    public function use_port():HasMany{
        return $this->hasMany(DevicePort::class,'device_id','id')
            ->where('status', 0);
    }

    public function free_port():HasMany{
        return $this->hasMany(DevicePort::class,'device_id','id')
            ->where('status', 1);
    }

    public static function addStation(string $stationId, $longitude,$latitude): int
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        return $redis->geoAdd(self::GEO_KEY, $longitude, $latitude, $stationId);
    }

    public static function getGeoDist($lng,$lat,$stationId){
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        $distance = $redis->geoDist(self::GEO_KEY, $lng, $lat, $stationId, 'km');
        return $distance;
    }

    public static function queryNearbyStations($longitude,$latitude, $radius, int $count = 999): array
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        $options = ['WITHDIST','WITHCOORD'];
        $result = $redis->geoRadius(self::GEO_KEY, $longitude, $latitude, $radius, 'km',$options);
        return $result;
    }

    public static function removeStation(string $stationId): int
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        // 注意：这里应该是 GEOREM 而不是 GEOREM，后者可能是个打字错误
        return $redis->zRem(self::GEO_KEY, $stationId);
    }

    public static function updateStation(string $stationId, float $newLongitude, float $newLatitude): bool
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        // 首先，尝试从Geo集合中移除旧的站点
        $removed = $redis->zRem(self::GEO_KEY, $stationId);

        // 如果成功移除了站点，则添加新的经纬度
        if ($removed === 1) {
            $added = $redis->geoAdd(self::GEO_KEY, $newLongitude, $newLatitude, $stationId);
            return $added === 1; // 返回是否成功添加
        }

        // 如果没有找到要删除的站点，则返回false
        return false;
    }

    /**
     * 设置设备在线
     * @param $mac
     * @param $fd
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws RedisException
     */
    public static function setDeviceOnline($mac,$fd):bool
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        $result = $redis->hSet('device_online', (string)$mac, (string)$fd);
        return is_int($result);
    }

    /**
     * 设置设备不在线
     * @param $mac
     * @return bool
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws RedisException
     */
    public static function setDeviceNotOnline($mac): bool
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        $result = $redis->hDel('device_online', (string)$mac);
        return is_int($result);
    }

    /**
     * 通过设备mac获取在线设备的FD客户端ID
     * @param $mac
     * @return string
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws RedisException
     */
    public static function getFdByMac($mac): string
    {
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        return (string)$redis->hGet('device_online', (string)$mac);
    }
}
